#include "ActionDispatcher.h"

//ActionDispatcher ActionDispatcher::m_instance;
ActionDispatcher* ActionDispatcher::m_instance = NULL;
int ActionDispatcher::m_nInitThreads = 16;
int ActionDispatcher::m_nMaxThreads = 16;

ActionDispatcher::ActionDispatcher(void) : m_listActions(), m_mutex(), m_sem()
{
    m_pThreadPool = new ThreadPool(ActionDispatcher::m_nInitThreads, 
        ActionDispatcher::m_nMaxThreads);

    //Start();    // thread pool manager is running now.
}

ActionDispatcher::~ActionDispatcher(void)
{
    if (m_pThreadPool != NULL)
    {
        delete m_pThreadPool;
        m_pThreadPool = NULL;
    }
}

ActionDispatcher* ActionDispatcher::GetInstance()
{
    if (m_instance == NULL)
    {
        m_instance = new ActionDispatcher();
    }
    return m_instance;
}

void ActionDispatcher::Assign(Action* pAction)
{
    m_mutex.Lock();
    m_listActions.push_back(pAction);
    m_mutex.Unlock();

    m_sem.Post();
}

void ActionDispatcher::Run()
{
    Action* pAction = NULL;
    sigset_t mask;
    if (0 != sigfillset(&mask))
    {
        //LogErrorToFile("threadManager sigfillset failed!");
    }
    if (0 != pthread_sigmask(SIG_SETMASK, &mask, NULL))
    {
        //LogErrorToFile("threadManager pthread_sigmask failed!");
    }
    while (true)
    {
        //printf("ActionDispatcher::Run");
        m_sem.Wait();
        m_mutex.Lock();
        if (!m_listActions.empty())
        {
            pAction = m_listActions.front();
            m_listActions.pop_front();
        }
        m_mutex.Unlock();
        OnAction(pAction);
    }
}

void ActionDispatcher::OnAction(Action* pAction)
{
    //LogInforToFile("ActionDispatcher::OnAction\n");
    if (!pAction)
    {
        //logError("threadManager received a null action!");
        return;
    }
    switch (pAction->GetType())
    {
    case Action::NEWMSG:
        if (m_pThreadPool->GetBusyThreadNumbers() < m_pThreadPool->GetMaxThreadNumbers())
        {
            if (pAction->GetJob()->GetStatus() == Job::IDLE)
            {
                pAction->GetJob()->SetStatus(Job::BUSY);
                m_pThreadPool->Assign(pAction->GetJob());
                delete pAction;
            }
        }
        else
        {
            m_mutex.Lock();
            m_listActions.push_front(pAction);
            m_mutex.Unlock();
            //logInfo("In onMsg , All threads are busy!");
        }
        break;
    case Action::JOBDONE:
        //LogInfoToFile("Action::JOBDONE");
        delete pAction;
        break;
    default:
        //logError("threadManager receive an unknow type Action!");
        break;
    }
}




